package cn.sylinx.horm.resource.parse;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import cn.sylinx.horm.core.common.Consts;
import cn.sylinx.horm.core.common.TypedParameter;
import cn.sylinx.horm.exception.HORMException;
import cn.sylinx.horm.util.Pair;

public class PlaceholderParser {

    public static final PlaceholderParser INSTANCE_QM = new PlaceholderParser("?{", "}");
    public static final PlaceholderParser INSTANCE_DEFAULT = new PlaceholderParser("#{", "}");
    
    private String startSymbol; // 开始占位符
    private String endSymbol; // 结束占位符

    public PlaceholderParser(String startSymbol, String endSymbol) {
        this.startSymbol = startSymbol;
        this.endSymbol = endSymbol;
    }

    public String getStartSymbol() {
        return startSymbol;
    }

    public void setStartSymbol(String startSymbol) {
        this.startSymbol = startSymbol;
    }

    public String getEndSymbol() {
        return endSymbol;
    }

    public void setEndSymbol(String endSymbol) {
        this.endSymbol = endSymbol;
    }

    public Pair parseSql(String sql, Map<String, Object> env) {

        StringBuilder preparedStatement = new StringBuilder();
        List<Object> preparedStatementParams = new ArrayList<Object>();

        parseSqlInner(sql, env, preparedStatement, preparedStatementParams);

        String rst = preparedStatement.toString();

        Object[] params = new Object[preparedStatementParams.size()];
        preparedStatementParams.toArray(params);

        return Pair.apply(rst, params);
    }

    private void parseSqlInner(String sql, Map<String, Object> env, StringBuilder preparedStatement, List<Object> preparedStatementParams) {

        if (sql == null) {
            throw new HORMException("sql is null");
        }

        int is = sql.indexOf(startSymbol);
        if (is == -1) {
            preparedStatement.append(sql);
            return;
        }

        String tmp = sql.substring(is);
        int is1 = tmp.indexOf(endSymbol);
        int ie = is1 + is;
        if (is1 == -1) {
            throw new HORMException("illegal statement");
        }

        String split = sql.substring(is + startSymbol.length(), ie);
        preparedStatementParams.add(getTypedParameter(split, env));

        String before = sql.substring(0, is) + "?";
        preparedStatement.append(before);
        String after = sql.substring(ie + endSymbol.length());

        parseSqlInner(after, env, preparedStatement, preparedStatementParams);
    }
    
    private Object getTypedParameter(String key, Map<String, Object> env) {
        
        Object param = env.get(key);
        // 参数类型
        Object parameterTypeObject = env.get(key + Consts.TYPED_PARAMETER_POSTFIX);
        if (!(parameterTypeObject instanceof Class)) {
            return param;
        }

        TypedParameter typedParameter = new TypedParameter();
        typedParameter.setParameter(param);
        typedParameter.setParameterType((Class<?>) parameterTypeObject);

        return typedParameter;
    }

}
